/*
    Heart of Gold engine management system
    Copyright (C) 2004 Heart of Gold development team

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package com.heartOfGold.view;

/*
 * The Enrichments setup page for the Megasquirt HOG_Component
 * @author Ryan Higgins
 * @date May 2004
 */
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.GridLayout;
import java.awt.Dimension;

import javax.swing.JButton;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
//import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.Box;

import com.heartOfGold.controller.Fuel;

import java.io.*;

/*
 */

public class FuelEnrichment extends JPanel implements ActionListener {
    private FuelMaster master;
    private Fuel model;
    private LabelField cPLoDeg, cPHiDeg, cPPrime, aEEnrich, aENumber, wEN40,
            wEN20, wE0, wE20, wE40, wE60, wE80, wE100, wE130, wE160, tPSTrig,
            accEnDur, aE2V, aE4V, aE8V, aE15V, coldAdd, coldMult, decelCut,
            egoTemp, numEvents, stepPercent, egoLimit, egoRPM, egoSwitch;
    private String cPLoDegCmp, cPHiDegCmp, cPPrimeCmp, aEEnrichCmp,
            aENumberCmp, wEN40Cmp, wEN20Cmp, wE0Cmp, wE20Cmp, wE40Cmp, wE60Cmp,
            wE80Cmp, wE100Cmp, wE130Cmp, wE160Cmp, tPSTrigCmp, accEnDurCmp,
            aE2VCmp, aE4VCmp, aE8VCmp, aE15VCmp, coldAddCmp, coldMultCmp,
            decelCutCmp, egoTempCmp, numEventsCmp, stepPercentCmp, egoLimitCmp,
            egoRPMCmp, egoSwitchCmp;

    private class LabelField extends JPanel {
        private JLabel theLabel;
        private JTextField theField;
        private int fieldColumns;
        private Dimension labelSize;

        public LabelField(final String label, final String longest) {
            fieldColumns = 5;
            theLabel = new JLabel(label);
            if (longest != null) {
                JLabel my = new JLabel(longest);
                labelSize = new Dimension(my.getPreferredSize());
                theLabel.setPreferredSize(labelSize);
            }
            theField = new JTextField(fieldColumns);
            theField.setText("0");
            theField.setHorizontalAlignment(JTextField.CENTER);
            add(theLabel);
            add(theField);
            theField.setActionCommand(theLabel.getText());
        }

        public void addActionListener(final ActionListener l) {
            theField.addActionListener(l);
        }

        public void update(final String fieldValue) {
            theField.setText(fieldValue);
        }

        public String getText() {
            return theField.getText();
        }

        public String getLabel() {
            return theLabel.getText();
        }

    }

    public FuelEnrichment(final FuelMaster m,
            final Fuel mod) {
        master = m;
        model = mod;
        setBorder(BorderFactory.createTitledBorder("Enrichment Setup"));

        // setup cranking pulsewidth
        JPanel crank = new JPanel(new GridLayout(3, 1));
        crank.setBorder(BorderFactory
                .createTitledBorder("Cranking Pulsewidth (ms)"));
        cPLoDeg = new LabelField("Pulsewidth at -40F", null);
        cPHiDeg = new LabelField("Pulsewidth at 170F", null);
        cPPrime = new LabelField("Priming Pulse", "PulseWidth at 170F");
        crank.add(cPLoDeg);
        crank.add(cPHiDeg);
        crank.add(cPPrime);

        // setup after start enrichment
        JPanel after = new JPanel(new GridLayout(2, 1));
        after.setBorder(BorderFactory.createTitledBorder("Afterstart"));
        aEEnrich = new LabelField("Enrichment (%)",
                "Number Of Ignition Cycles");
        aENumber = new LabelField("Number Of Ignition Cycles", null);
        after.add(aEEnrich);
        after.add(aENumber);

        // setup the warmup enrichments
        JPanel warmup = new JPanel(new GridLayout(10, 1));
        warmup.setBorder(BorderFactory.createTitledBorder("Warmup (%)"));
        wE160 = new LabelField("160F", "160F");
        wE130 = new LabelField("130F", "160F");
        wE100 = new LabelField("100F", "160F");
        wE80 = new LabelField("80F", "160F");
        wE60 = new LabelField("60F", "160F");
        wE40 = new LabelField("40F", "160F");
        wE20 = new LabelField("20F", "160F");
        wE0 = new LabelField("0F", "160F");
        wEN20 = new LabelField("-20F", "160F");
        wEN40 = new LabelField("-40F", "160F");
        warmup.add(wE160);
        warmup.add(wE130);
        warmup.add(wE100);
        warmup.add(wE80);
        warmup.add(wE60);
        warmup.add(wE40);
        warmup.add(wE20);
        warmup.add(wE0);
        warmup.add(wEN20);
        warmup.add(wEN40);

        // setup the acceleration enrichments
        String accLong = "Acceleration Enrichment Duration (second)";
        Box accel = Box.createHorizontalBox();
        accel.setBorder(BorderFactory
                .createTitledBorder("Acceleration Enrichment"));
        JPanel accelLeft = new JPanel(new GridLayout(5, 1));
        JPanel accelRight = new JPanel(new GridLayout(4, 1));
        accelRight.setBorder(BorderFactory
                .createTitledBorder("Accel Enrich (ms)"));
        tPSTrig = new LabelField("TPS Trigger Threshold (Volts/Second)",
                accLong);
        accEnDur = new LabelField("Acceleration Enrichment Duration (Second)",
                accLong);
        coldAdd = new LabelField("Cold-Accel Enrichment Add-On (ms)", accLong);
        coldMult = new LabelField("Cold-Accel Enrichment Multiplier (%)",
                accLong);
        decelCut = new LabelField("Deceleration Fuel Cut (%)", accLong);
        accelLeft.add(tPSTrig);
        accelLeft.add(accEnDur);
        accelLeft.add(coldAdd);
        accelLeft.add(coldMult);
        accelLeft.add(decelCut);
        aE2V = new LabelField("2V/Sec ", null);
        aE4V = new LabelField("4V/Sec ", null);
        aE8V = new LabelField("8V/Sec ", null);
        aE15V = new LabelField("15V/Sec", null);
        accelRight.add(aE2V);
        accelRight.add(aE4V);
        accelRight.add(aE8V);
        accelRight.add(aE15V);
        accel.add(accelLeft);
        accel.add(accelRight);

        // setup the Exhaust gas oxygen stuff
        Box exhaust = Box.createHorizontalBox();
        JPanel exhaustLeft = new JPanel(new GridLayout(3, 1));
        JPanel exhaustRight = new JPanel(new GridLayout(3, 1));
        exhaust.setBorder(BorderFactory
                .createTitledBorder("Exhaust Gas Oxygen"));
        String leftLong = "Number Of Ignition Events Between Steps";
        String rightLong = "EGO Active Above (RPM) ";
        egoTemp = new LabelField("Coolant Temp Activation (F)", leftLong);
        numEvents = new LabelField("Number Of Ignition Events Between Steps",
                leftLong);
        stepPercent = new LabelField("EGO step (%)", leftLong);
        egoLimit = new LabelField("EGO +/- Limit (%)", rightLong);
        egoRPM = new LabelField("EGO Active Above (RPM) ", rightLong);
        egoSwitch = new LabelField("EGO Switch Point (V)", rightLong);
        exhaustLeft.add(egoTemp);
        exhaustLeft.add(numEvents);
        exhaustLeft.add(stepPercent);
        exhaustRight.add(egoLimit);
        exhaustRight.add(egoRPM);
        exhaustRight.add(egoSwitch);
        exhaust.add(exhaustLeft);
        exhaust.add(exhaustRight);

        // setup buttons
        JPanel buttons = new JPanel();
        JButton get = new JButton("Get From Controller");
        JButton send = new JButton("Send To Controller");
        JButton done = new JButton("Done");
        get.addActionListener(this);
        send.addActionListener(this);
        done.addActionListener(this);
        buttons.add(get);
        buttons.add(send);
        buttons.add(done);
        // buttons.setBorder(BorderFactory.createEtchedBorder());

        // collect the pieces arrange them and add them to the screen
        JPanel upleft = new JPanel(new GridLayout(1, 2));
        upleft.add(crank);
        upleft.add(after);
        Box left = Box.createVerticalBox();
        left.add(upleft);
        left.add(accel);
        Box upper = Box.createHorizontalBox();
        upper.add(left);
        upper.add(warmup);
        Box all = Box.createVerticalBox();
        all.add(upper);
        all.add(exhaust);
        all.add(buttons);

        add(all);
    }

    public final void actionPerformed(final ActionEvent ae) {
        String command = ae.getActionCommand();
        if (command.equals("Get From Controller")) {
            try {
                model.getConstants();
            } catch (IOException e) {
            }
            return;
        }

        if (command.equals("Send To Controller")) {
            try {
                addChange();
                model.writeChanges();
                model.burn();
            } catch (IOException e) {
            }
            return;
        }

        if (command.equals("Done")) {
            master.switchScreen("Main");
            return;
        }

        JOptionPane.showMessageDialog(this,
                "This function is not yet implemented", "Not Implemented",
                JOptionPane.INFORMATION_MESSAGE);

    }

    public final void update(final int[] constants) {
        // Updates all the fields of the screen and private strings to compare
        // to when the addChange method is called

        // set cranking pulse width
        cPLoDeg.update("" + (double) constants[64] / 10);
        cPLoDegCmp = new String(cPLoDeg.getText());
        cPHiDeg.update("" + (double) constants[65] / 10);
        cPHiDegCmp = new String(cPHiDeg.getText());
        cPPrime.update("" + (double) constants[119] / 10);
        cPPrimeCmp = new String(cPPrime.getText());

        // set after start enrichments
        aEEnrich.update("" + constants[66]);
        aEEnrichCmp = new String(aEEnrich.getText());
        aENumber.update("" + constants[67]);
        aENumberCmp = new String(aENumber.getText());

        // set warmup enrichments
        wEN40.update("" + constants[68]);
        wEN40Cmp = new String(wEN40.getText());
        wEN20.update("" + constants[69]);
        wEN20Cmp = new String(wEN20.getText());
        wE0.update("" + constants[70]);
        wE0Cmp = new String(wE0.getText());
        wE20.update("" + constants[71]);
        wE20Cmp = new String(wE20.getText());
        wE40.update("" + constants[72]);
        wE40Cmp = new String(wE40.getText());
        wE60.update("" + constants[73]);
        wE60Cmp = new String(wE60.getText());
        wE80.update("" + constants[74]);
        wE80Cmp = new String(wE80.getText());
        wE100.update("" + constants[75]);
        wE100Cmp = new String(wE100.getText());
        wE130.update("" + constants[76]);
        wE130Cmp = new String(wE130.getText());
        wE160.update("" + constants[77]);
        wE160Cmp = new String(wE160.getText());

        // Acceleration enrichments
        tPSTrig.update("" + (double) constants[83] / 5);
        tPSTrigCmp = new String(tPSTrig.getText());
        accEnDur.update("" + (double) constants[84] / 10);
        accEnDurCmp = new String(accEnDur.getText());
        aE2V.update("" + constants[78]);
        aE2VCmp = new String(aE2V.getText());
        aE4V.update("" + constants[79]);
        aE4VCmp = new String(aE4V.getText());
        aE8V.update("" + constants[80]);
        aE8VCmp = new String(aE8V.getText());
        aE15V.update("" + constants[81]);
        aE15VCmp = new String(aE15V.getText());
        coldAdd.update("" + (double) constants[82] / 10);
        coldAddCmp = new String(coldAdd.getText());
        coldMult.update("" + constants[123]);
        coldMultCmp = new String(coldMult.getText());
        decelCut.update("" + constants[85]);
        decelCutCmp = new String(decelCut.getText());

        // Exhaust gas oxygen stuff
        egoTemp.update("" + (constants[86] - 40));
        egoTempCmp = new String(egoTemp.getText());
        numEvents.update("" + constants[87]);
        numEventsCmp = new String(numEvents.getText());
        stepPercent.update("" + constants[88]);
        stepPercentCmp = new String(stepPercent.getText());
        egoLimit.update("" + constants[89]);
        egoLimitCmp = new String(egoLimit.getText());
        egoRPM.update("" + constants[120] * 100);
        egoRPMCmp = new String(egoRPM.getText());
        egoSwitch.update("" + ((double) constants[122] / 255.0 * 5.0));
        egoSwitchCmp = new String(egoSwitch.getText());

    }

    public final void addChange() {
        // If the field is different from the private string add the change then
        // write and burn the changes
        int toSend = 0;
        // set cranking pulse width
        if (!cPLoDegCmp.equals(cPLoDeg.getText())) {
            toSend = (int) (Double.parseDouble(cPLoDeg.getText()) * 10);
            model.addChange(64, toSend);
        }
        if (!cPHiDegCmp.equals(cPHiDeg.getText())) {
            toSend = (int) (Double.parseDouble(cPHiDeg.getText()) * 10);
            model.addChange(65, toSend);
        }
        if (!cPPrimeCmp.equals(cPPrime.getText())) {
            toSend = (int) (Double.parseDouble(cPPrime.getText()) * 10);
            model.addChange(119, toSend);
        }
        // set after start enrichments
        if (!aEEnrichCmp.equals(aEEnrich.getText())) {
            toSend = (int) (Double.parseDouble(aEEnrich.getText()));
            model.addChange(66, toSend);
        }
        if (!aENumberCmp.equals(aENumber.getText())) {
            toSend = (int) (Double.parseDouble(aENumber.getText()));
            model.addChange(67, toSend);
        }

        // set warmup enrichments
        if (!wEN40Cmp.equals(wEN40.getText())) {
            toSend = (int) (Double.parseDouble(wEN40.getText()));
            model.addChange(68, toSend);
        }
        if (!wEN20Cmp.equals(wEN20.getText())) {
            toSend = (int) (Double.parseDouble(wEN20.getText()));
            model.addChange(69, toSend);
        }
        if (!wE0Cmp.equals(wE0.getText())) {
            toSend = (int) (Double.parseDouble(wE0.getText()));
            model.addChange(70, toSend);
        }
        if (!wE20Cmp.equals(wE20.getText())) {
            toSend = (int) (Double.parseDouble(wE20.getText()));
            model.addChange(71, toSend);
        }
        if (!wE40Cmp.equals(wE40.getText())) {
            toSend = (int) (Double.parseDouble(wE40.getText()));
            model.addChange(72, toSend);
        }
        if (!wE60Cmp.equals(wE60.getText())) {
            toSend = (int) (Double.parseDouble(wE60.getText()));
            model.addChange(73, toSend);
        }
        if (!wE80Cmp.equals(wE80.getText())) {
            toSend = (int) (Double.parseDouble(wE80.getText()));
            model.addChange(74, toSend);
        }
        if (!wE100Cmp.equals(wE100.getText())) {
            toSend = (int) (Double.parseDouble(wE100.getText()));
            model.addChange(75, toSend);
        }
        if (!wE130Cmp.equals(wE130.getText())) {
            toSend = (int) (Double.parseDouble(wE130.getText()));
            model.addChange(76, toSend);
        }
        if (!wE160Cmp.equals(wE160.getText())) {
            toSend = (int) (Double.parseDouble(wE160.getText()));
            model.addChange(77, toSend);
        }

        // Acceleration enrichments
        if (!tPSTrigCmp.equals(tPSTrig.getText())) {
            toSend = (int) (Double.parseDouble(tPSTrig.getText()) * 5);
            model.addChange(83, toSend);
        }
        if (!accEnDurCmp.equals(accEnDur.getText())) {
            toSend = (int) (Double.parseDouble(accEnDur.getText()) * 10);
            model.addChange(84, toSend);
        }
        if (!aE2VCmp.equals(aE2V.getText())) {
            toSend = (int) (Double.parseDouble(aE2V.getText()));
            model.addChange(78, toSend);
        }
        if (!aE4VCmp.equals(aE4V.getText())) {
            toSend = (int) (Double.parseDouble(aE4V.getText()));
            model.addChange(79, toSend);
        }
        if (!aE8VCmp.equals(aE8V.getText())) {
            toSend = (int) (Double.parseDouble(aE8V.getText()));
            model.addChange(80, toSend);
        }
        if (!aE15VCmp.equals(aE15V.getText())) {
            toSend = (int) (Double.parseDouble(aE15V.getText()));
            model.addChange(81, toSend);
        }
        if (!coldAddCmp.equals(coldAdd.getText())) {
            toSend = (int) (Double.parseDouble(coldAdd.getText()) * 10);
            model.addChange(82, toSend);
        }
        if (!coldMultCmp.equals(coldMult.getText())) {
            toSend = (int) (Double.parseDouble(coldMult.getText()));
            model.addChange(123, toSend);
        }
        if (!decelCutCmp.equals(decelCut.getText())) {
            toSend = (int) (Double.parseDouble(decelCut.getText()));
            model.addChange(85, toSend);
        }

        // Exhaust gas oxygen stuff
        if (!egoTempCmp.equals(egoTemp.getText())) {
            toSend = (int) (Double.parseDouble(egoTemp.getText()) + 40);
            model.addChange(86, toSend);
        }
        if (!numEventsCmp.equals(numEvents.getText())) {
            toSend = (int) (Double.parseDouble(numEvents.getText()));
            model.addChange(87, toSend);
        }
        if (!stepPercentCmp.equals(stepPercent.getText())) {
            toSend = (int) (Double.parseDouble(stepPercent.getText()));
            model.addChange(88, toSend);
        }
        if (!egoLimitCmp.equals(egoLimit.getText())) {
            toSend = (int) (Double.parseDouble(egoLimit.getText()));
            model.addChange(89, toSend);
        }
        if (!egoRPMCmp.equals(egoRPM.getText())) {
            toSend = (int) (Double.parseDouble(egoRPM.getText()) / 100);
            model.addChange(120, toSend);
        }
        if (!egoSwitchCmp.equals(egoSwitch.getText())) {
            toSend = (int) (Double.parseDouble(egoSwitch.getText()) * 255 / 5);
            model.addChange(122, toSend);
        }

        // Write the changes and burn them to the controller
        try {
            model.writeChanges();
        } catch (IOException e) {
        }
    }

    private boolean checkRange(final String toCheck, final double lo,
            final double hi, final String name) {
        double value = Double.parseDouble(toCheck);
        if ((value < lo) || (value > hi)) {
            JOptionPane.showMessageDialog(this, name
                    + " must have a value between " + lo + " and " + hi + "!",
                    "Danger! Warning! Houston, we have a problem...",
                    JOptionPane.WARNING_MESSAGE);
            return false;
        }
        return true;
    }

}
